﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
using DocumentFormat.OpenXml;

public class WordBookmarkReplacer
{
    /// <summary>
    /// Word模板生成入口：替换书签、占位符、表格
    /// </summary>
    public static void GenerateWord(string templatePath, string outputPath, BookData bookData)
    {
        if (!File.Exists(templatePath))
            throw new FileNotFoundException("模板文件不存在: " + templatePath);

        // 复制模板到输出文件（保留原模板）
        File.Copy(templatePath, outputPath, true);

        using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(outputPath, true))
        {
            // 替换书签
            if (bookData.marks?.Count > 0)
                ReplaceBookmarks(wordDoc, bookData.marks);

            // 替换占位符
            if (bookData.placeholders?.Count > 0)
                ReplacePlaceholders(wordDoc, bookData.placeholders);

            // 插入表格数据
            if (bookData.tables?.Count > 0)
            {
                foreach (var kv in bookData.tables)
                {
                    InsertRowsToTable(wordDoc, kv.Key, kv.Value);
                }
            }

            // 插入图片
            if (bookData.images?.Count > 0)
            {
                foreach (var imageData in bookData.images)
                {
                    InsertImage(wordDoc, imageData.BookmarkName, imageData.ImagePath, imageData.Width, imageData.Height);
                }
            }

            wordDoc.MainDocumentPart.Document.Save();
        }
    }

    #region === 书签替换 ===
    public static void ReplaceBookmarks(WordprocessingDocument wordDoc, Dictionary<string, string> replacements)
    {
        var mainPart = wordDoc.MainDocumentPart;
        if (mainPart?.Document?.Body == null)
            throw new Exception("Word 文档不包含有效内容。");

        var bookmarks = mainPart.Document.Body.Descendants<BookmarkStart>();

        foreach (var bookmark in bookmarks)
        {
            string bookmarkName = bookmark.Name;
            if (!replacements.ContainsKey(bookmarkName))
                continue;

            string newText = replacements[bookmarkName] ?? string.Empty;
            var parent = bookmark.Parent;

            // 删除 BookmarkStart 与 BookmarkEnd 之间的内容
            var nextElement = bookmark.NextSibling();
            while (nextElement != null && !(nextElement is BookmarkEnd be && be.Id == bookmark.Id))
            {
                var toRemove = nextElement;
                nextElement = nextElement.NextSibling();
                toRemove.Remove();
            }

            // 插入新文本
            Run run = new Run(new Text(newText));
            parent.InsertAfter(run, bookmark);
        }
    }
    #endregion

    #region === 占位符替换 ===
    public static void ReplacePlaceholders(WordprocessingDocument doc, Dictionary<string, string> replacements)
    {
        var body = doc.MainDocumentPart.Document.Body;
        var texts = body.Descendants<Text>().ToList();

        foreach (var text in texts)
        {
            if (string.IsNullOrEmpty(text.Text)) continue;

            foreach (var kv in replacements)
            {
                string placeholder = kv.Key;
                string newValue = kv.Value ?? string.Empty;

                if (text.Text.Contains(placeholder))
                {
                    text.Text = text.Text.Replace(placeholder, newValue);
                }
            }
        }
    }
    #endregion


    #region === 表格插入 ===

    /// <summary>
    /// 向指定索引的表格插入多行数据（基于模板行克隆），内容显示正常且不会多余换行
    /// </summary>
    /// <param name="doc">打开的 Word 文档对象</param>
    /// <param name="tableIndex">表格索引（0-based）</param>
    /// <param name="data">要插入的行数据，每个 List&lt;string&gt; 表示一行</param>

    public static void InsertRowsToTable(WordprocessingDocument doc, int tableIndex, List<List<string>> data)
    {
        var body = doc.MainDocumentPart.Document.Body;
        var tables = body.Elements<Table>().ToList();

        if (tableIndex < 0 || tableIndex >= tables.Count)
            throw new IndexOutOfRangeException($"表格索引 {tableIndex} 不存在（当前文档只有 {tables.Count} 个表格）。");

        var table = tables[tableIndex];
        var allRows = table.Elements<TableRow>().ToList();
        if (allRows.Count == 0)
            throw new Exception("目标表格没有任何行，无法复制模板行。");

        var templateRow = allRows.Last();

        foreach (var rowData in data)
        {
            var newRow = (TableRow)templateRow.CloneNode(true);
            var cells = newRow.Elements<TableCell>().ToList();

            for (int i = 0; i < cells.Count && i < rowData.Count; i++)
            {
                var cell = cells[i];
                string newText = rowData[i] ?? string.Empty;

                // 找到所有的 Text 节点并替换内容
                var texts = cell.Descendants<Text>().ToList();

                if (texts.Count > 0)
                {
                    // 保留第一个 Text 节点，替换其内容
                    texts[0].Text = newText;

                    // 删除其他多余的 Text 节点
                    for (int j = 1; j < texts.Count; j++)
                    {
                        texts[j].Remove();
                    }
                }
                else
                {
                    // 如果没有 Text 节点，创建新的
                    var paragraph = cell.Elements<Paragraph>().FirstOrDefault();
                    if (paragraph == null)
                    {
                        paragraph = new Paragraph();
                        cell.Append(paragraph);
                    }

                    var run = new Run(new Text(newText));
                    paragraph.Append(run);
                }
            }

            table.InsertAfter(newRow, allRows.Last());
            allRows.Add(newRow);
        }
    }
    #endregion



    #region === 图片插入 ===

    /// <summary>
    /// 在指定书签位置插入图片
    /// </summary>
    public static void InsertImage(WordprocessingDocument doc, string bookmarkName, string imagePath, long width = 300, long height = 150)
    {
        if (string.IsNullOrEmpty(bookmarkName) || string.IsNullOrEmpty(imagePath) || !File.Exists(imagePath))
            return;

        var mainPart = doc.MainDocumentPart;
        var body = mainPart.Document.Body;

        // 找到书签
        var bookmark = body.Descendants<BookmarkStart>()
            .FirstOrDefault(b => b.Name == bookmarkName);

        if (bookmark == null)
            return;

        // 添加图片到文档部件
        var imagePart = mainPart.AddImagePart(ImagePartType.Png);
        using (var stream = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
        {
            imagePart.FeedData(stream);
        }

        string relationshipId = mainPart.GetIdOfPart(imagePart);

        // Word 单位换算：1 厘米 = 360000 EMU；1 英寸 = 914400 EMU
        const long emusPerPixel = 9525; // ≈ 96 DPI
        var cx = width * emusPerPixel;
        var cy = height * emusPerPixel;

        // 构造图片 Drawing 元素
        var element =
            new Drawing(
                new DW.Inline(
                    new DW.Extent() { Cx = cx, Cy = cy },
                    new DW.EffectExtent() { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L },
                    new DW.DocProperties() { Id = (UInt32Value)1U, Name = "Picture" },
                    new DW.NonVisualGraphicFrameDrawingProperties(
                        new A.GraphicFrameLocks() { NoChangeAspect = true }),
                    new A.Graphic(
                        new A.GraphicData(
                            new PIC.Picture(
                                new PIC.NonVisualPictureProperties(
                                    new PIC.NonVisualDrawingProperties()
                                    {
                                        Id = (UInt32Value)0U,
                                        Name = Path.GetFileName(imagePath)
                                    },
                                    new PIC.NonVisualPictureDrawingProperties()),
                                new PIC.BlipFill(
                                    new A.Blip()
                                    {
                                        Embed = relationshipId,
                                        CompressionState = A.BlipCompressionValues.Print
                                    },
                                    new A.Stretch(new A.FillRectangle())),
                                new PIC.ShapeProperties(
                                    new A.Transform2D(
                                        new A.Offset() { X = 0L, Y = 0L },
                                        new A.Extents() { Cx = cx, Cy = cy }),
                                    new A.PresetGeometry(
                                        new A.AdjustValueList()
                                    )
                                    { Preset = A.ShapeTypeValues.Rectangle })
                            )
                        )
                        { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" })
                )
                {
                    DistanceFromTop = 0U,
                    DistanceFromBottom = 0U,
                    DistanceFromLeft = 0U,
                    DistanceFromRight = 0U,
                });

        // 在书签处插入图片
        var parent = bookmark.Parent;
        parent.InsertAfter(new Run(element), bookmark);
    }
    #endregion















    #region === 数据结构 ===
    public class BookData
    {
        /// <summary>书签替换内容</summary>
        public Dictionary<string, string> marks { get; set; } = new Dictionary<string, string>();

        /// <summary>占位符替换内容</summary>
        public Dictionary<string, string> placeholders { get; set; } = new Dictionary<string, string>();

        /// <summary>表格插入数据（Key=表格索引，Value=要插入的数据行）</summary>
        public Dictionary<int, List<List<string>>> tables { get; set; } = new Dictionary<int, List<List<string>>>();

        /// <summary>图片插入数据</summary>
        public List<ImageData> images { get; set; } = new List<ImageData>();
    }


    public class ImageData
    {
        /// <summary>书签名称</summary>
        public string BookmarkName { get; set; }

        /// <summary>图片文件路径</summary>
        public string ImagePath { get; set; }

        /// <summary>图片宽度（像素）</summary>
        public long Width { get; set; } = 200;

        /// <summary>图片高度（像素）</summary>
        public long Height { get; set; } = 150;
    }
    #endregion
}
